use bevy_ecs::prelude::Component;

use rapier2d::prelude::{ColliderHandle, RigidBodyHandle, RigidBodyType};

use uuid::Uuid;

use crate::{
    color::Rgba,
    function::resource::texture::Texture,
    math::{Matrix4f, Vector3f},
    pool::Handle,
};

use super::camera::CameraType;



#[derive(Debug, Clone, Component)]
pub struct IdComponent {
    pub id: Uuid,
}

impl IdComponent {
    pub fn new(id: Uuid) -> Self {
        Self { id }
    }
}

#[derive(Debug, Clone, Component, serde::Serialize, serde::Deserialize)]
pub struct TagComponent {
    pub tag: String,
}

#[derive(Debug, Clone, Component)]
pub struct TransformComponent {
    pub translation: Vector3f,
    pub rotation: Vector3f,
    pub scale: Vector3f,
    /// 父节点的世界坐标变换
    pub world_transform_base: Matrix4f,
}

impl TransformComponent {
    pub fn new(translation: Vector3f) -> Self {
        Self {
            translation,
            rotation: Vector3f::ZERO,
            scale: Vector3f::new(1.0, 1.0, 1.0),
            world_transform_base: Matrix4f::identity(),
        }
    }

    pub fn get_transform(&self) -> Matrix4f {
        self.world_transform_base
            * (Matrix4f::new_translation(&self.translation) * Matrix4f::new_scale(&self.scale))
    }
}

#[derive(serde::Serialize, serde::Deserialize)]
pub struct Transform {
    pub translation: Vector3f,
    pub rotation: Vector3f,
    pub scale: Vector3f,
}

#[derive(Debug, Clone, Component, serde::Serialize, serde::Deserialize)]
pub struct SpriteRendererComponent {
    pub color: Rgba,
    #[serde(default)]
    pub texture: Handle<Texture>,
    pub path: String,
    pub factor: f32,
}

impl SpriteRendererComponent {
    pub fn new(color: impl Into<Rgba>) -> Self {
        Self {
            color: color.into(),
            texture: Handle::try_get_default_handle(),
            factor: 1.0,
            path: String::from("assets/1.png"),
        }
    }
}

#[derive(Debug, Clone, Component, serde::Serialize, serde::Deserialize)]
pub struct Rigidbody2DComponent {
    /// 真实 rigidbody 的句柄
    pub body_handle: RigidBodyHandle,
    /// 运动体的 质量  默认为 1
    pub mass: f32,
    /// 运动体的类型 默认 fixed 即不受任何外力影响
    pub rb_type: RigidBodyType,
    /// 是否开启连续碰撞检测
    pub ccd: bool,
}

impl Rigidbody2DComponent {
    pub fn new() -> Self {
        Rigidbody2DComponent {
            body_handle: RigidBodyHandle::invalid(),
            mass: 1.0,
            rb_type: rapier2d::prelude::RigidBodyType::Fixed,
            ccd: false,
        }
    }
}

#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub enum Collider2DShape {
    Ball,
    Capsule,
    Compound,
    Cuboid,
    HalfSpace,
    HeightField,
    Polyline,
    RoundShape,
    Segment,
    Shape,
    TriMesh,
    Triangle,
}

#[derive(Debug, Clone, Component, serde::Serialize, serde::Deserialize)]
pub struct Collider2DComponent {
    /// 碰撞体的 句柄
    pub handle: ColliderHandle,
    /// 碰撞体形状 ， 默认为 Cuboid
    pub shape: Collider2DShape,
    /// 反弹力 0-1
    pub restitution: f32,
    /// 摩擦力
    pub friction: f32,
}

impl Collider2DComponent {
    pub fn new() -> Self {
        Collider2DComponent {
            handle: ColliderHandle::invalid(),
            shape: super::components::Collider2DShape::Ball,
            restitution: 0.7,
            friction: 0.5,
        }
    }
}

#[derive(Debug, Clone, Component, serde::Serialize, serde::Deserialize)]
pub struct CameraComponent {
    pub camera_ty: CameraType,
    pub perspective_fovy: f32,
    pub orthographic_size: f32,
    pub clip_near: f32,
    pub clip_far: f32,
    pub aspect_ratio: f32,
    pub fixed_aspect_ratio: bool,
    pub primary:bool
}


impl CameraComponent {
    pub fn perspective() -> Self {
        Self {
            camera_ty: CameraType::Perspective,
            perspective_fovy: 45.0_f32.to_radians(),
            orthographic_size: 1.0,
            clip_near: 0.1,
            clip_far: 1000.0,
            aspect_ratio: 1.0,
            fixed_aspect_ratio: false,
            primary:false
        }
    }

    pub fn orthographic() -> Self {
        Self {
            camera_ty: CameraType::Orthographic,
            perspective_fovy: 0.0,
            orthographic_size: 10.0,
            clip_near: -1.0,
            clip_far: 1.0,
            aspect_ratio: 0.0,
            fixed_aspect_ratio: false,
            primary:false
        }
    }
}


#[derive(Debug,Clone, serde::Serialize, serde::Deserialize)]
pub enum ScriptProps {
    Number(f32),
    String(String),
    Boolean(bool),
}

#[derive(Debug, Clone, Component, serde::Serialize, serde::Deserialize)]
pub struct ScriptComponent {
    pub path:String,
    pub class_name:String,
    pub enable:bool,
    pub props:Vec<ScriptProps>
}

impl ScriptComponent {
    pub fn new(path:&str) -> Self {
        let file_name = std::path::Path::new(path).file_name().unwrap().to_str().unwrap().to_owned();

        let name = file_name.split(".").collect::<Vec<&str>>()[0];
        Self {
            path:path.to_owned(),
            class_name:name.to_owned(),
            enable:true,
            props:vec![]
        }
    }
}